#include "page/home.h"

pthread_t homeTimeTID;
pthread_t homeTouchTID;
pthread_t homeMQ2TID;
pthread_t homeGY39TID;
volatile bool isHomeFinished = false;
volatile bool isLEDOn = false;
volatile bool isBeepOn = false;

Point temperatureXY = {0, 0};
Point humidityXY = {0, 0};
Point smokeXY = {0, 0};
Point brightXY = {0, 0};

int8_t clickedIndex = -1;
Button buttons[RIGHT_PANEL_ITEM_COUNT];

ColorInt buttonPressedColor[] = {
    0xFF6A8372,
    RED,
    0xFFF8DF70,
    0xFFF05E1C
};

char buttonIcons[][30] = {
    "./res/picture.bmp",
    "./res/stop.bmp",
    "./res/led.bmp",
    "./res/buzzer.bmp",
    "./res/smoke.bmp",
    "./res/brightness.bmp"
};

uint8_t (*buttonTexts[])[2][CN_CHAR_H][CN_CHAR_W / 8] = {
    &CN_TU_KU,
    &CN_ZHONG_ZHI,
    &CN_DENG_GUAN,
    &CN_FENG_MING,
    NULL,
    NULL
};

void* ShowTime(void* args) {
    Screen_DrawTime(Time_ToSeconds(Time_MakeLocal()), 90, 75, BLACK, NORMAL);

    return NULL;
}

void MQ2Callback(void* arg) {
    int32_t* smoke = (int32_t*)arg;

    Screen_SetPaintColor(WHITE);
    Screen_DrawFilledRect(smokeXY.x, smokeXY.y, CN_CHAR_W, CN_CHAR_H);

    uint8_t(*text)[CN_CHAR_H / 8];
    ColorInt color;
    if (*smoke >= 200) {
        color = RED;
        text = CN_CHA_LIANG_YOU[0];
    } else if (*smoke >= 60) {
        color = BLACK;
        text = CN_CHA_LIANG_YOU[1];
        UART_CtrlBLED(BEEP, true);
    } else {
        color = GREEN;
        text = CN_CHA_LIANG_YOU[2];
        UART_CtrlBLED(BEEP, false);
    }

    Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, text, smokeXY.x, smokeXY.y, color);

    sleep(1);
}

void GY39Callback(void* arg) {
    GY39* data = (GY39*)arg;

    if (data->wd != 0 || data->sd != 0) {
        Screen_DrawFilledRectWithColor(temperatureXY.x, temperatureXY.y, ASCII_CHAR_W * 2, ASCII_CHAR_H, WHITE);
        Screen_DrawFilledRectWithColor(humidityXY.x, humidityXY.y, ASCII_CHAR_W * 2, ASCII_CHAR_H, WHITE);
        Screen_DrawFilledRectWithColor(brightXY.x, brightXY.y, CN_CHAR_W, CN_CHAR_H, WHITE);

        Screen_DrawNumber(data->wd, temperatureXY.x, temperatureXY.y, BLACK);
        Screen_DrawNumber(data->sd, humidityXY.x, humidityXY.y, BLACK);

        uint8_t(*text)[CN_CHAR_H / 8];
        ColorInt color;
        if (data->gz >= 100) {
            color = GREEN;
            text = CN_CHA_LIANG_YOU[2];
        } else if (data->gz >= 10) {
            color = BLACK;
            text = CN_CHA_LIANG_YOU[1];
        } else {
            color = RED;
            text = CN_CHA_LIANG_YOU[0];
        }

        Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, text, brightXY.x, brightXY.y, color);
    }

    sleep(1);
}

void DrawButtonText(Button button) {
    uint8_t(*text)[2][CN_CHAR_H][CN_CHAR_W / 8] = buttonTexts[clickedIndex];
    if (text == NULL) {
        return;
    }

    uint16_t x0 = button.x + ICON_SIZE + 20;
    uint16_t y0 = button.y + (button.height - CN_CHAR_H) / 2;
    Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, (uint8_t(*)[CN_CHAR_W / 8]) text[0], x0, y0, BLACK);
    Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, (uint8_t(*)[CN_CHAR_W / 8]) text + CN_CHAR_H, x0 + CN_CHAR_W, y0, BLACK);
}

void DrawButton(Button button) {
    if (button.isPressed) {
        Screen_SetPaintColor(buttonPressedColor[clickedIndex]);
    } else {
        Screen_SetPaintColor(WHITE);
    }

    Screen_DrawRoundedRect(button.x, button.y, button.width, button.height, 10);
    Screen_ShowBMPByFile(buttonIcons[clickedIndex], button.x + 10, button.y + (button.height - ICON_SIZE) / 2);
    DrawButtonText(button);
}

void DrawItems() {
    Screen_SetPaintColor(WHITE);

    uint16_t itemSpace = 30;
    uint16_t itemMargin = 50;

    uint16_t panelSplitX = 400;

    uint16_t panelLeftWidth = panelSplitX - itemSpace / 2 - itemMargin;
    uint16_t panelLeftHeight = SCREEN_H - itemMargin * 2;
    Screen_DrawRoundedRect(itemMargin, itemMargin, panelLeftWidth, panelLeftHeight, 10);

    Screen_SetPaintColor(BLACK);
    Screen_SetPaintStrokeWidth(4);
    Screen_DrawLine(itemMargin, itemMargin * 2 + ASCII_CHAR_H, itemMargin + panelLeftWidth, itemMargin * 2 + ASCII_CHAR_H);
    Screen_DrawLine(itemMargin + panelLeftWidth / 2 - 2, itemMargin * 2 + ASCII_CHAR_H, itemMargin + panelLeftWidth / 2 - 2, itemMargin + panelLeftHeight);

    temperatureXY.x = itemMargin + 55;
    temperatureXY.y = itemMargin + panelLeftHeight - 140 - ASCII_CHAR_H - 15;

    humidityXY.x = itemMargin + panelLeftWidth - 65 - ICON_SIZE;
    humidityXY.y = itemMargin + panelLeftHeight - 140 - ASCII_CHAR_H - 15;

    Screen_DrawNumber(0, temperatureXY.x, temperatureXY.y, BLACK);
    Screen_DrawNumber(0, humidityXY.x, humidityXY.y, BLACK);

    Screen_ShowBMPByFile("./res/temperature.bmp", itemMargin + 55, itemMargin + panelLeftHeight - 140);
    Screen_ShowBMPByFile("./res/humidity.bmp", itemMargin + panelLeftWidth - 60 - ICON_SIZE, itemMargin + panelLeftHeight - 140);

    Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, CN_WEN_SHI[0], itemMargin + 65, itemMargin + panelLeftHeight - 80, BLACK);
    Screen_DrawChar(CN_CHAR_W, CN_CHAR_H, CN_WEN_SHI[1], itemMargin + panelLeftWidth - 50 - ICON_SIZE, itemMargin + panelLeftHeight - 80, BLACK);

    uint16_t rightPanelStartX = panelSplitX + itemSpace / 2;
    uint16_t rightPanelStartY = itemMargin;

    uint16_t rightPanelEndX = SCREEN_W - itemMargin;
    uint16_t rightPanelEndY = SCREEN_H - itemMargin;

    uint16_t buttonWidth = (rightPanelEndX - rightPanelStartX - (RIGHT_PANEL_ITEM_X - 1) * itemSpace) / RIGHT_PANEL_ITEM_X;
    uint16_t buttonHeight = (rightPanelEndY - rightPanelStartY - (RIGHT_PANEL_ITEM_Y - 1) * itemSpace) / RIGHT_PANEL_ITEM_Y;

    for (size_t i = 0; i < RIGHT_PANEL_ITEM_Y; i++) {
        uint16_t y = rightPanelStartY + i * (buttonHeight + itemSpace);
        for (size_t j = 0; j < RIGHT_PANEL_ITEM_X; j++) {
            uint16_t x = rightPanelStartX + j * (buttonWidth + itemSpace);

            clickedIndex = j + i * RIGHT_PANEL_ITEM_X;
            Button* button = &buttons[clickedIndex];
            button->x = x;
            button->y = y;
            button->width = buttonWidth;
            button->height = buttonHeight;
            button->isCanPresse = buttonTexts[clickedIndex] != NULL;
            button->isPressed = false;

            // printf("Button[%d] %d, %d, %d, %d\n", clickedIndex, button->x, button->y, button->width, button->height);

            DrawButton(*button);
        }
    }

    smokeXY.x = buttons[4].x + ICON_SIZE + 20;
    smokeXY.y = buttons[4].y + (buttons[4].height - CN_CHAR_H) / 2;

    brightXY.x = buttons[5].x + ICON_SIZE + 20;
    brightXY.y = buttons[5].y + (buttons[5].height - CN_CHAR_H) / 2;

    clickedIndex = -1;
}

void* MonitorTouch(void* arg) {
    if (!Touch_CanRead()) {
        return NULL;
    }

    int16_t x, y, x0, y0;
    struct input_event ev;
    while (true) {
        pthread_testcancel();
        if (Touch_ReadEvent(&ev) == sizeof(ev)) {
            if (ev.type == EV_ABS) {
                if (ev.code == ABS_X) {
                    x = ev.value;
                } else if (ev.code == ABS_Y) {
                    y = ev.value;
                }
            } else if (ev.type == EV_KEY) {
                if (ev.code == BTN_TOUCH) {
                    if (ev.value == 1) {
                        x0 = 1.0 * x / TOUCH_W * SCREEN_W;
                        y0 = 1.0 * y / TOUCH_H * SCREEN_H;

                        for (size_t i = 0; i < RIGHT_PANEL_ITEM_COUNT; i++) {
                            Button* button = &buttons[i];
                            if (button->isCanPresse && x0 >= button->x && x0 < button->x + button->width && y0 >= button->y && y0 < button->y + button->height) {
                                button->isPressed = 1;
                                clickedIndex = i;
                                DrawButton(*button);
                                break;
                            }
                        }
                    } else if (ev.value == 0) {
                        if (clickedIndex != -1) {
                            Button* button = &buttons[clickedIndex];
                            button->isPressed = 0;
                            DrawButton(*button);

                            if (clickedIndex == 0) {
                                clickedIndex = -1;
                                nextPage = GALLERY;
                                goto THREAD_END;
                            } else if (clickedIndex == 1) {
                                clickedIndex = -1;
                                nextPage = FREE_ALL;
                                goto THREAD_END;
                            } else if (clickedIndex == 2) {
                                clickedIndex = -1;
                                isLEDOn ^= true;
                                UART_CtrlBLED(LED_ALL, isLEDOn);
                            } else if (clickedIndex == 3) {
                                clickedIndex = -1;
                                isBeepOn ^= true;
                                UART_CtrlBLED(BEEP, isBeepOn);
                            }
                        }
                    }
                }
            }
        }
    }

THREAD_END:
    printf("Home hiding...\n");
    Home_Free();
    return NULL;
}

void Home_Show() {
    printf("Home Showing...\n");

    Screen_ShowBMPByFile("./res/00.bmp", 0, 0);
    DrawItems();
    pthread_create(&homeTimeTID, NULL, ShowTime, NULL);
    pthread_create(&homeTouchTID, NULL, MonitorTouch, NULL);
    pthread_create(&homeMQ2TID, NULL, UART_GetMQ2, (void*)MQ2Callback);
    pthread_create(&homeGY39TID, NULL, UART_GetGY39, (void*)GY39Callback);
    isHomeFinished = false;
    pthread_join(homeTouchTID, NULL);
}

void Home_Free() {
    if (isHomeFinished) {
        return;
    }

    isHomeFinished = true;
    pthread_cancel(homeGY39TID);
    pthread_cancel(homeMQ2TID);
    pthread_cancel(homeTouchTID);
    pthread_cancel(homeTimeTID);
}
